package cn.objectspace.filessh.service;

import com.jcraft.jsch.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;

@Service
public class FileSshService {
    private JSch jsch;
    private Session session;
    private Channel channel;


    public FileSshService() {
        jsch = new JSch();
    }

    public void connect(String host, int port, String username, String password) throws JSchException {
        session = jsch.getSession(username, host, port);
        session.setPassword(password);
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();
    }

    public void disconnect() {
        if (channel != null && channel.isConnected()) {
            channel.disconnect();
        }
        if (session != null && session.isConnected()) {
            session.disconnect();
        }
    }

    public String executeCommand(String command) throws JSchException, IOException {
        channel = session.openChannel("exec");
        ((ChannelExec) channel).setCommand(command);

        InputStream commandOutput = channel.getInputStream();
        channel.connect();

        StringBuilder outputBuffer = new StringBuilder();
        byte[] buffer = new byte[1024];
        int bytesRead;

        while ((bytesRead = commandOutput.read(buffer)) > 0) {
            outputBuffer.append(new String(buffer, 0, bytesRead));
        }

        channel.disconnect();
        return outputBuffer.toString();
    }

    public void uploadFile(MultipartFile file, String remotePath) throws JSchException, IOException, SftpException {
        ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
        sftpChannel.connect();

        try (InputStream inputStream = file.getInputStream()) {
            sftpChannel.put(inputStream, remotePath + "/" + file.getOriginalFilename());
        }

        sftpChannel.disconnect();
    }

    public InputStream downloadFile(String remoteFilePath) throws JSchException, IOException, SftpException {
        ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
        sftpChannel.connect();

        try {
            InputStream inputStream = sftpChannel.get(remoteFilePath);
            return inputStream;
        } finally {
            // 不要关闭 inputStream 和 sftpChannel 这里，让调用方负责关闭
        }
    }

    public List<Map<String, String>> listFiles(String path) throws JSchException, SftpException {
        List<Map<String, String>> entries = new ArrayList<>();
        ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
        sftpChannel.connect();
        Vector<ChannelSftp.LsEntry> files = sftpChannel.ls(path);
        for (ChannelSftp.LsEntry entry : files) {
            Map<String, String> entryMap = new HashMap<>();
            entryMap.put("name", entry.getFilename());
            entryMap.put("type", entry.getAttrs().isDir() ? "directory" : "file");
            entries.add(entryMap);
        }
        return entries;
    }


    public List<Map<String,String>> searchFilesInDirectoryAndSubdirectories(String directory, String searchContent,Boolean isIncludeSubdirectory) throws JSchException, IOException {
        List<Map<String,String>> result = new ArrayList<>();
        // 打开SSH通道并执行find命令
        Channel channel = session.openChannel("exec");
        String findCommand ;
        if(isIncludeSubdirectory){
            findCommand = "find " + directory + " -type f -name '*" + searchContent + "*'";
        }else {
            findCommand = "find " + directory + " -maxdepth 1 -type f -name '*" + searchContent + "*'";
        }
        ((ChannelExec) channel).setCommand(findCommand);

        InputStream in = channel.getInputStream();
        channel.connect();

        // 读取命令输出
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line;
        while ((line = reader.readLine()) != null) {
            Map<String, String> entryMap = new HashMap<>();
            entryMap.put("file",line);
            result.add(entryMap);
        }
        // 关闭通道
        channel.disconnect();
        searchFilesRecursively(directory,searchContent,isIncludeSubdirectory,result);
        return  result;
    }

    private void searchFilesRecursively(String directory, String searchContent,Boolean isIncludeSubdirectory,List<Map<String,String>> result) throws JSchException, IOException {
        // 打开SSH通道并执行find命令
        Channel channel = session.openChannel("exec");
        String findCommand;
        if(isIncludeSubdirectory){
             findCommand = "find " + directory + " -type d -name '*" + searchContent + "*'";

        }else {
            findCommand = "find " + directory + " -maxdepth 1 -type d -name '*" + searchContent + "*'";
        }
        ((ChannelExec) channel).setCommand(findCommand);

        InputStream in = channel.getInputStream();
        channel.connect();

        // 读取命令输出
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line;
        while ((line = reader.readLine()) != null) {
            Map<String, String> entryMap = new HashMap<>();
            entryMap.put("folder",line);
            result.add(entryMap);
        }
        // 关闭通道
        channel.disconnect();
    }

}
